this.elements = []
this.deepElements = []

function HTMLParser(html) {
	if (!(this instanceof HTMLParser)) {
		return new HTMLParser(html);
	}
	html = html || ''
	html = html.replace(/[\r\n]/g, '')
	let elements = []
	let deep = 0
	let preIndex = 0
	let preTagType = null // start、selfClosing、end
	let curTagType = null // start、selfClosing、end
	// 这些标签是自封闭的,防止标签不闭合
	let selfClosingLabels = [
		'meta', 'base', 'br', 'hr', 'img', 'input', 'col', 'frame', 'link', 'area', 'param', 'object', 'embed',
		'keygen',
		'source'
	]
	html.replace(/(<([\w-]+)[^>]*\/?>)|(<\/([\w-]+)[^>]*>)/g,
		function(all, startTag, startTagName, endTag, endTagName, index) {
			// 如果是开始标签
			if (startTagName) {
				// 判断是不是自闭和标签
				selfClosing = /\/>/g.test(startTag) || selfClosingLabels.includes(startTagName.toLowerCase())
				curTagType = selfClosing ? 'selfClosing' : 'start'
				// innerText 代表中间的文本，但是到了这一步并不知道它的子孩子是标签还是普通文本，所以先不赋值
				let tmp_obj = {
					tagName: startTagName.toUpperCase(),
					startIndex: index,
					selfClosing: selfClosing,
					tagContent: startTag,
					deep: deep
				}
				// 如果标签内有属性，提取属性
				if (/<[\w-]+([^>]+)\/?>/.test(startTag)) {
					RegExp.$1.replace(/([\w-]+)=((['"])([\w\W]*?)\3|([^\s]*))/g, function() {
						tmp_obj[arguments[1]] = arguments[4] || arguments[5]
					});
				}

				elements.push(tmp_obj);
				deep += tmp_obj.selfClosing ? 0 : 1
			}
			// 是结束标签
			else {
				curTagType = 'end'
				deep -= 1
				// 地址指向
				let tmp_element = elements[elements.length - 1]
				if (deep === tmp_element.deep) {
					tmp_element.innerText = html.substring(
						tmp_element.startIndex + tmp_element.tagContent.length, index
					).replace(/&nbsp;/g, ' ')
				}
			}

			// 标签外文本
			if (preIndex !== index &&
				(curTagType !== 'end' || preTagType !== 'start')) {
				let tmp_element = elements[elements.length - 1]
				tmp_element.outerText = html.substring(preIndex, index).replace(/&nbsp;/g, ' ')
			}
			preIndex = index + all.length
			preTagType = curTagType
		}
	);
	this.elements = JSON.parse(JSON.stringify(elements))
	this.elementToDeep(elements)
}

HTMLParser.prototype.elementToDeep = function(elements) {
	let deepElements = [],
		t_deepElements = []
	let t_deep = 0
	elements.map(item => {
		// 深度增大，说明是上一个标签的子孩子
		if (item.deep > t_deep) {
			let tmp_child = t_deepElements[t_deepElements.length - 1]
			tmp_child.children = tmp_child.children || []
			tmp_child.children.push(item)
			t_deepElements = t_deepElements[t_deepElements.length - 1].children
			t_deep = item.deep
		}
		// 深度不变，说明是上一个标签的兄弟
		else if (item.deep === t_deep) {
			t_deepElements.push(item)
		}
		// 深度变小，说明上一个标签是结束标签，也就是一条分支的遍历已经结束
		else {
			t_deepElements = deepElements
			for (let i = 0; i < item.deep; i++) {
				t_deepElements = t_deepElements[t_deepElements.length - 1].children
			}
			t_deepElements.push(item)
			t_deep = item.deep
		}

		if (item.deep === 0) {
			deepElements = t_deepElements
		}
	})

	this.deepElements = JSON.parse(JSON.stringify(deepElements))
}

HTMLParser.prototype.find = function(str) {
	const _this = this
	let result = [];
	str.replace(/[.]([^.#\s]*)|[#]([^.#\s]*)|([^.#\s][^.#\s]*)/g, function(all, className, idName, tagName, index) {
		if (result.length === 0) {
			result = JSON.parse(JSON.stringify(_this.deepElements));
		}

		if (className) {
			result = deepFind('class', result, className)
		}
		if (idName) {
			result = deepFind('id', result, idName)
		}
		if (tagName) {
			result = deepFind('tagName', result, tagName.toUpperCase())
		}
	})
	return result
}

function deepFind(attr, arr, value) {
	let result = []
	arr.map(item => {
		if (item.hasOwnProperty(attr) && item[attr] === value) {
			result.push(item)
		}

		if (item.hasOwnProperty('children') && item.children.length > 0) {
			let tmp_result = deepFind(attr, item.children, value)
			result.push(...tmp_result)
		}
	})
	return result
}

module.exports = HTMLParser;
